--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 82e41b2d087d0b724ba86a4352b20af38ec34a55
Parents : c0b0ddf
Author : Ivan <e46112d44649266d71fe2193e00a4710>
Signature : T66BB85Valid, signed by author
Date : 2026-07-20T13:56:50-05:00
docs: update
Changes
13 files changed, 308 insertions(+), 28 deletions(-)
Diff
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 00000000..f2ae1980
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,6 @@
+# MeshChatX agent entry
+
+Start at [docs/agents/README.md](docs/agents/README.md).
+
+For architecture and invariants, read [docs/agents/overview.md](docs/agents/overview.md).
+For mesh design, read [docs/agents/conventions/reticulum-zen.md](docs/agents/conventions/reticulum-zen.md).
diff --git a/docs/agents/README.md b/docs/agents/README.md
index c5fe9d46..cd13fe4f 100644
--- a/docs/agents/README.md
+++ b/docs/agents/README.md
@@ -1,7 +1,7 @@
# Agent guidance for MeshChatX
Neutral, tool-agnostic notes for automated agents and human contributors who work like agents.
-This tree is **not** part of the in-app user documentation. End-user docs live under `docs/en/`.
+This tree is not part of the in-app user documentation. End-user docs live under `docs/en/`.
## Start here
@@ -11,10 +11,11 @@ This tree is **not** part of the in-app user documentation. End-user docs live u
4. Open a [skills/](skills/) guide when the task matches that workflow.
Root [AGENTS.md](../../AGENTS.md) is a short pointer to this directory.
-Cursor rules under `.cursor/rules/`:
-- Always on: `meshchatx-core.mdc`, `reticulum-zen-gates.mdc`
-- Globs: `meshchatx-backend.mdc`, `meshchatx-frontend.mdc`, `meshchatx-android.mdc`, `meshchatx-tests.mdc`
+Optional editor rules (if present under `.cursor/rules/` or similar):
+
+- Always on: MeshChatX core standards and Reticulum Zen gates
+- Globs: backend, frontend, Android, tests
## Layout
@@ -26,7 +27,7 @@ Cursor rules under `.cursor/rules/`:
| [conventions/frontend.md](conventions/frontend.md) | Vue UI |
| [conventions/backend.md](conventions/backend.md) | Python / HTTP / SQLite |
| [conventions/android.md](conventions/android.md) | Android WebView bridge |
-| [conventions/tests.md](conventions/tests.md) | Test placement and verification |
+| [conventions/tests.md](conventions/tests.md) | Test placement, oracles, verification |
## Skills
@@ -37,6 +38,16 @@ Cursor rules under `.cursor/rules/`:
| [page-toast-tests](skills/page-toast-tests/SKILL.md) | New pages, toasts, i18n, tests |
| [contribution-registries](skills/contribution-registries/SKILL.md) | Nav, tools, commands, settings search, WS event wiring |
+### Mesh protocols (RNS / LXMF / LXST / RRC)
+
+| Skill | Use when |
+| ---------------------------------------------------------------- | --------------------------------------------------------- |
+| [reticulum-design-gates](skills/reticulum-design-gates/SKILL.md) | Any mesh design review against Zen of Reticulum |
+| [rns-link-api](skills/rns-link-api/SKILL.md) | Generic RNS Link WebSocket / plugin transport |
+| [lxmf-messaging](skills/lxmf-messaging/SKILL.md) | LXMF send/receive, stamps, propagation, attachments |
+| [lxst-telephony](skills/lxst-telephony/SKILL.md) | LXST calls, audio WS, telephony managers |
+| [rrc-relay-chat](skills/rrc-relay-chat/SKILL.md) | Relay Chat hubs, rooms, +k keys, moderation, client state |
+
### Identity and data
| Skill | Use when |
@@ -48,26 +59,26 @@ Cursor rules under `.cursor/rules/`:
### Security and plugins
-| Skill | Use when |
-| ------------------------------------------------------------------ | --------------------------------------------- |
-| [reticulum-design-gates](skills/reticulum-design-gates/SKILL.md) | Mesh design review against Zen of Reticulum |
-| [auth-csrf-ws-security](skills/auth-csrf-ws-security/SKILL.md) | CSRF, auth, WS mutator denylist |
-| [plugin-install-security](skills/plugin-install-security/SKILL.md) | Plugin install, RSG, permissions, integrity |
-| [rns-link-api](skills/rns-link-api/SKILL.md) | Generic RNS Link WebSocket / plugin transport |
+| Skill | Use when |
+| ------------------------------------------------------------------ | ------------------------------------------- |
+| [auth-csrf-ws-security](skills/auth-csrf-ws-security/SKILL.md) | CSRF, auth, WS mutator denylist |
+| [plugin-install-security](skills/plugin-install-security/SKILL.md) | Plugin install, RSG, permissions, integrity |
### Platforms and boot
-| Skill | Use when |
-| ---------------------------------------------------------------------- | ------------------------------------------------- |
-| [deferred-network-startup](skills/deferred-network-startup/SKILL.md) | HTTP-up vs RNS-ready, status, 503s, RNS panic |
-| [electron-frozen-packaging](skills/electron-frozen-packaging/SKILL.md) | Frozen desktop spawn, loading, crash recovery |
-| [android-webview-bridge](skills/android-webview-bridge/SKILL.md) | Android chooser MIME, storage, WebView navigation |
+| Skill | Use when |
+| ---------------------------------------------------------------------- | --------------------------------------------- |
+| [deferred-network-startup](skills/deferred-network-startup/SKILL.md) | HTTP-up vs RNS-ready, status, 503s, RNS panic |
+| [electron-frozen-packaging](skills/electron-frozen-packaging/SKILL.md) | Frozen desktop spawn, loading, crash recovery |
+| [android-webview-bridge](skills/android-webview-bridge/SKILL.md) | Android chooser MIME, storage, WebView nav |
### Verification
-| Skill | Use when |
-| -------------------------------------- | ---------------------------------------- |
-| [test-loop](skills/test-loop/SKILL.md) | Focused verification without hung shells |
+| Skill | Use when |
+| ---------------------------------------------------------- | ---------------------------------------------------- |
+| [test-loop](skills/test-loop/SKILL.md) | Focused verification without hung shells |
+| [test-oracles](skills/test-oracles/SKILL.md) | Property/fuzz oracles: accept/reject, not soft fuzz |
+| [exploratory-testing](skills/exploratory-testing/SKILL.md) | Adversarial exploration to find bugs with hypotheses |
## Product docs (users)
diff --git a/docs/agents/conventions/backend.md b/docs/agents/conventions/backend.md
index 4cb24f0a..e728ecd1 100644
--- a/docs/agents/conventions/backend.md
+++ b/docs/agents/conventions/backend.md
@@ -9,3 +9,5 @@ Applies when editing `meshchatx/**/*.py`.
- Under Landlock, memory-pressure must not force FILE temp for conversation queries.
- Keep conversation list queries slim: truncate content, derive attachment flags in SQL, avoid shipping full `fields` blobs.
- Identity restore validates size and empty payloads. Preserve existing identity metadata on re-import.
+- No backticks in code comments. Prefer plain words or quoted identifiers.
+- RRC / LXMF / LXST changes: open the matching skill under `docs/agents/skills/` and run oracle-style tests when behaviour changes.
diff --git a/docs/agents/conventions/core.md b/docs/agents/conventions/core.md
index 25e1e943..86ca080b 100644
--- a/docs/agents/conventions/core.md
+++ b/docs/agents/conventions/core.md
@@ -5,6 +5,8 @@
- Prefer `task` targets (`format`, `lint`, `test:quick`, `test:backend`, `test:frontend`).
- Minimal diffs. Match nearby style. Keep SPDX headers on new project files (`0BSD` unless file already differs).
- No emojis in repo text. No TODO/FIXME comment noise.
+- No emdashes or semicolons in comments or docs you write.
+- No backticks in code comments. Prefer plain words or quoted identifiers.
- Do not commit/push unless asked.
- User-visible UI strings: i18n keys. Action feedback: `ToastUtils`.
- Do not invent install/run flows when Taskfile already covers them.
diff --git a/docs/agents/conventions/frontend.md b/docs/agents/conventions/frontend.md
index e34ddae7..d1f5dbd9 100644
--- a/docs/agents/conventions/frontend.md
+++ b/docs/agents/conventions/frontend.md
@@ -6,7 +6,9 @@ Applies when editing `meshchatx/src/frontend/**/*.{vue,js}`.
- API calls go through `window.api` (not ad-hoc axios imports in pages).
- Toasts: `ToastUtils.success|error|warning|info|loading|dismiss`.
- New top-level pages need: route in `main.js`, nav entry when discoverable, `en.json` keys, frontend tests.
+- When adding user-visible strings, update `en.json` and the other maintained locale files under `meshchatx/src/frontend/locales/` with real translations (not English copies).
- Sidebar unread pills live on nav entries in `coreNavEntries.js` and counters in `GlobalState`. Do not bring back a header notification bell for that job.
- Do not use `_`-prefixed keys in Vue `data()` (`vue/no-reserved-keys`).
- File inputs: prefer broad `accept` for identity keys (`.bin,.key,.identity,application/octet-stream,*/*`). Database restore stays `.zip`.
- Prefer existing MaterialDesignIcon / layout patterns over new design systems.
+- No backticks in code comments. Prefer plain words or quoted identifiers.
diff --git a/docs/agents/conventions/tests.md b/docs/agents/conventions/tests.md
index 61e583a5..170ec1c5 100644
--- a/docs/agents/conventions/tests.md
+++ b/docs/agents/conventions/tests.md
@@ -27,6 +27,9 @@ Prefer:
- Closed reason sets: on `ValueError`, the message is one of the known machine reasons
- Round-trip or shape invariants when the API is pure parsing
+Full skill: `docs/agents/skills/test-oracles/SKILL.md`.
+Exploratory bug hunting: `docs/agents/skills/exploratory-testing/SKILL.md`.
+
## Extended Edge Case Tester (EECT) and Live Validation (LV)
- EECT packs live under `tests/backend/eect/packs/` and use marker `eect`.
diff --git a/docs/agents/overview.md b/docs/agents/overview.md
index c39b4990..484ba98c 100644
--- a/docs/agents/overview.md
+++ b/docs/agents/overview.md
@@ -37,7 +37,7 @@ MeshChatX sits on Reticulum. Agents must not invent cloud-era or IP-era designs
- Philosophy: [Zen of Reticulum](https://reticulum.network/manual/zen.html)
- Conventions: `docs/agents/conventions/reticulum-zen.md`
- Checklist skill: `docs/agents/skills/reticulum-design-gates/SKILL.md`
-- Cursor always-on rule: `.cursor/rules/reticulum-zen-gates.mdc`
+- Always-on editor rule (when present): reticulum Zen gates under project rules
Short form: no mandatory cloud center, address destination hashes, assume hostile links, design for scarcity and delay, keep code transport-agnostic, keep identity state scoped.
@@ -302,12 +302,13 @@ meshchatx --restore-db /path/to/backup.zip
1. No emojis in code, markdown, or docs you write for this repo.
2. No TODO / FIXME noise comments.
3. No emdashes or semicolons in comments or docs you write.
-4. Do not create markdown docs unless asked (except agent guidance under `docs/agents/` when requested).
-5. Do not commit or push unless the user asks.
-6. Do not generate exploit PoCs, malware, or attack tooling.
-7. Prefer minimal diffs. Match nearby style.
-8. Do not invent install/run flows when Taskfile already covers them.
-9. Mesh-facing designs must pass Zen / architecture gates (`reticulum-zen.md` / `reticulum-design-gates`).
+4. No backticks in code comments. Prefer plain words or quoted identifiers.
+5. Do not create markdown docs unless asked (except agent guidance under `docs/agents/` when requested).
+6. Do not commit or push unless the user asks.
+7. Do not generate exploit PoCs, malware, or attack tooling.
+8. Prefer minimal diffs. Match nearby style.
+9. Do not invent install/run flows when Taskfile already covers them.
+10. Mesh-facing designs must pass Zen / architecture gates (`reticulum-zen.md` / `reticulum-design-gates`).
## High-risk change checklist
@@ -337,5 +338,5 @@ Before finishing work in these areas, verify the matching invariants:
## Agent guidance index
- `docs/agents/README.md` - index of conventions and skills
-- `docs/agents/conventions/` - surface-specific rules including Reticulum Zen
-- `docs/agents/skills/` - focused workflows including reticulum-design-gates, pages, registries, identity restore/switch, Landlock/SQLite, migrations/backups, auth/CSRF/WS, plugins, RNS Link API, deferred startup, Electron packaging, Android bridge, and test loop
+- `docs/agents/conventions/` - surface-specific rules including Reticulum Zen and test oracles
+- `docs/agents/skills/` - focused workflows including reticulum-design-gates, RRC / LXMF / LXST, pages, registries, identity restore/switch, Landlock/SQLite, migrations/backups, auth/CSRF/WS, plugins, RNS Link API, deferred startup, Electron packaging, Android bridge, test loop, test-oracles, and exploratory-testing
diff --git a/docs/agents/skills/exploratory-testing/SKILL.md b/docs/agents/skills/exploratory-testing/SKILL.md
new file mode 100644
index 00000000..060c122d
--- /dev/null
+++ b/docs/agents/skills/exploratory-testing/SKILL.md
@@ -0,0 +1,55 @@
+# Skill: exploratory-testing
+
+Hunt bugs with explicit hypotheses and oracle-backed confirmation. Use when the user asks to find bugs, fuzz a subsystem, or audit edge cases beyond happy-path unit tests.
+
+## When to use
+
+- New or recently changed mesh protocols (RNS, LXMF, LXST, RRC)
+- Security-sensitive surfaces (ACL, keys, auth, path handling)
+- After a feature lands and needs adversarial review
+- Soft fuzz suites that need real oracles
+
+## Method
+
+1. Map the state machine or ACL matrix from code (not from memory alone).
+2. Write 5 to 15 concrete hypotheses (Hn) with file references and predicted wrong behaviour.
+3. For each high-priority hypothesis, write a failing oracle test first when possible.
+4. Confirm with a focused pytest or vitest run. Fix only confirmed bugs unless asked to report only.
+5. Record intentional behaviours (example IRC-style outside messages without +n) instead of changing them by accident.
+
+## Hypothesis quality
+
+Good:
+
+- Non-member PART fans PARTED to real members (server.py _handle_part)
+- Kick ERROR leaves client still in hub.rooms (manager.py _handle_error)
+
+Bad:
+
+- Maybe something is wrong with chat
+- Fuzz random bytes and ensure no crash
+
+## Priority order for mesh hubs and clients
+
+1. ACL ordering (founder/op promotion before +k / +i)
+2. Membership lies (phantom JOIN/PART, kick without peer notify)
+3. Client/hub desync on ERROR
+4. Persistence roundtrips (TOML, CBOR history, encrypted keys)
+5. Rate limits and DoS stuck states
+6. Cross-identity leakage
+
+## Deliverable shape
+
+When reporting to the user:
+
+- Confirmed bugs (fixed or still open)
+- Oracle tests added
+- Intentional behaviours left alone
+- Remaining hypotheses not yet tested
+
+## Related
+
+- `docs/agents/skills/test-oracles/SKILL.md`
+- `docs/agents/skills/rrc-relay-chat/SKILL.md`
+- `docs/agents/skills/reticulum-design-gates/SKILL.md`
+- `docs/agents/conventions/tests.md`
diff --git a/docs/agents/skills/lxmf-messaging/SKILL.md b/docs/agents/skills/lxmf-messaging/SKILL.md
new file mode 100644
index 00000000..ecc9b1a6
--- /dev/null
+++ b/docs/agents/skills/lxmf-messaging/SKILL.md
@@ -0,0 +1,42 @@
+# Skill: lxmf-messaging
+
+Change LXMF messaging, stamps, propagation, or attachments without breaking local-first mesh delivery or identity scoping.
+
+## When to use
+
+- Outbound/inbound LXMF, conversations, receipts, stamps
+- Propagation nodes, sync, inbound cancel, transfer limits
+- Attachments, images, RNCP handoff from chat
+- Config knobs that map to LXMRouter behaviour
+
+## Intent
+
+LXMF is store-and-forward mail on Reticulum. Do not require clearnet, DNS, or a central API to deliver messages. Address peers by destination hash and aspect `lxmf.delivery`.
+
+## Key paths
+
+| Area | Path |
+| ------------------------ | --------------------------------------------------------- |
+| Identity / router wiring | `meshchatx/src/backend/identity_context.py` |
+| Message handler | `meshchatx/src/backend/message_handler.py` (and related) |
+| HTTP/WS surface | `meshchatx/meshchat.py` |
+| Frontend conversations | `meshchatx/src/frontend/components/` conversation viewers |
+| Config | config managers / settings UI for LXMF options |
+
+## Gates
+
+1. Missing path: request path, allow propagate, surface recoverable state. No infinite spinner for LoRa-class delay.
+2. Payload size justified. Large files use RNCP or explicit transfer tools, not giant chat blobs.
+3. No cross-identity inbox or cache sharing.
+4. Do not log private keys or unredacted message bodies by default.
+5. Stamp and validation settings must match installed lxmf/rns versions.
+
+## Verification
+
+Prefer focused backend tests around the changed manager, plus frontend tests when UI sends or displays messages.
+
+```bash
+uv run pytest tests/backend/test_phased_startup_guards.py -q --tb=short
+```
+
+Also: `reticulum-design-gates`, `deferred-network-startup`, `identity-switch-teardown`.
diff --git a/docs/agents/skills/lxst-telephony/SKILL.md b/docs/agents/skills/lxst-telephony/SKILL.md
new file mode 100644
index 00000000..88024227
--- /dev/null
+++ b/docs/agents/skills/lxst-telephony/SKILL.md
@@ -0,0 +1,38 @@
+# Skill: lxst-telephony
+
+Change LXST telephony or call audio without treating MeshChatX as a cloud PBX or leaking identity-scoped call state.
+
+## When to use
+
+- TelephoneManager, call setup/teardown, ringing, voicemail
+- `/ws/telephone/audio` or related audio bridges
+- Adversarial or security tests for telephony
+- UI call screens and permissions
+
+## Intent
+
+LXST runs over Reticulum Links. Address callees by identity/destination hash. No mandatory TURN/SIP cloud for core calls. Local HTTPS UI is control plane for this device only.
+
+## Key paths
+
+| Area | Path |
+| ------------------ | ----------------------------------------------------------------- |
+| Telephony managers | `meshchatx/src/backend/` telephone / ringtone / voicemail modules |
+| Identity wiring | `meshchatx/src/backend/identity_context.py` |
+| Adversarial tests | `tests/backend/test_lxst_telephony_adversarial.py` |
+| Frontend call UI | telephone-related Vue components under `meshchatx/src/frontend/` |
+
+## Gates
+
+1. Tear down call and audio resources on identity switch.
+2. Do not block the whole UI on real-time ACK over constrained links. Show recoverable call states.
+3. Auth-guard WS mutators that start or answer calls when password auth is enabled.
+4. Keep audio paths identity-scoped. No shared in-memory call tables across identities.
+
+## Verification
+
+```bash
+uv run pytest tests/backend/test_lxst_telephony_adversarial.py -q --tb=short
+```
+
+Also: `reticulum-design-gates`, `auth-csrf-ws-security`, `identity-switch-teardown`.
diff --git a/docs/agents/skills/rrc-relay-chat/SKILL.md b/docs/agents/skills/rrc-relay-chat/SKILL.md
new file mode 100644
index 00000000..68464002
--- /dev/null
+++ b/docs/agents/skills/rrc-relay-chat/SKILL.md
@@ -0,0 +1,63 @@
+# Skill: rrc-relay-chat
+
+Implement or harden Reticulum Relay Chat (RRC) hubs and clients without breaking membership, +k keys, or identity scoping.
+
+## When to use
+
+- Relay Chat UI, HTTP/WS APIs, hub hosting, moderation commands
+- Room keys (+k), invite-only (+i), kick/ban/part behaviour
+- Client history, auto-rejoin, stored room keys
+- Spec alignment with https://rrc.kc1awv.net/ (hub conventions such as +k are rrcd-compatible extensions)
+
+## Core model
+
+- Aspect: `rrc.hub`. Address hubs by destination hash, not IP.
+- Hub-and-spoke over RNS Links. Rooms are hub-local labels.
+- JOIN body is empty in core wire docs. MeshChatX hubs may put a room key string in the JOIN body for +k.
+- Local HTTPS UI is not the mesh. Peers are not REST clients of MeshChatX.
+
+## Key paths
+
+| Area | Path |
+| ----------------- | ------------------------------------------------- |
+| Protocol | `meshchatx/src/backend/rrc/protocol.py` |
+| Client hubs | `meshchatx/src/backend/rrc/manager.py` |
+| Hosted hub | `meshchatx/src/backend/rrc/server.py` |
+| Commands | `meshchatx/src/backend/rrc/hub_commands.py` |
+| Room ACL | `meshchatx/src/backend/rrc/room_registry.py` |
+| rooms.toml | `meshchatx/src/backend/rrc/rooms_toml.py` |
+| Client key crypto | `meshchatx/src/backend/rrc/room_key_crypto.py` |
+| Key DAO | `meshchatx/src/backend/database/rrc_room_keys.py` |
+| UI | `meshchatx/src/frontend/components/relay/` |
+
+## Non-negotiables
+
+1. Do not promote founder/ops before +k / +i checks pass.
+2. Non-member PART must not fan out PARTED.
+3. Kick/ban must fan PARTED to remaining members and force client leave on ERROR.
+4. Client room keys: AES-GCM wrapped with HKDF from identity private key. Never return plaintext keys from list APIs.
+5. Hub room keys may live in rooms.toml (hub-local). Public API exposes `has_key` only.
+6. Quote rooms.toml table names so dotted room names roundtrip.
+7. Identity-scoped state only. Removing a hub clears stored keys for that hub.
+
+## Modes (hub conventions)
+
+| Flag | Meaning |
+| ---- | -------------------------------------------- |
+| +k | Key required to JOIN (unless op or invited) |
+| +i | Invite-only |
+| +n | No outside messages (non-members cannot MSG) |
+| +m | Moderated (need voice) |
+| +p | Private (hide from list / who restrictions) |
+| +t | Topic ops-only |
+
+Without +n, non-members can MSG an existing room (IRC-like). Kick removes membership. Enable +n if kicked users must stay silent.
+
+## Tests
+
+```bash
+uv run pytest tests/backend/test_rrc_oracle_bugs.py tests/backend/test_rrc_room_keys.py tests/backend/test_rrc_server.py tests/backend/test_rrc_moderation.py -q --tb=short
+pnpm exec vitest run tests/frontend/RelayChatPage.test.js
+```
+
+Use oracle and exploratory skills when hunting RRC bugs.
diff --git a/docs/agents/skills/test-oracles/SKILL.md b/docs/agents/skills/test-oracles/SKILL.md
new file mode 100644
index 00000000..cfa82335
--- /dev/null
+++ b/docs/agents/skills/test-oracles/SKILL.md
@@ -0,0 +1,55 @@
+# Skill: test-oracles
+
+Write property, fuzz, and security tests that decide accept or reject with an independent oracle. Never soft-fuzz that only checks nothing crashed.
+
+## When to use
+
+- Adding Hypothesis or randomized tests
+- Security or ACL coverage (auth, room keys, path jail, CSRF)
+- Protocol decode/encode, parsers, normalizers
+- Reviewing tests that look like fuzz but assert nothing
+
+## What an oracle is
+
+An oracle predicts the correct outcome from the input alone (or from a simpler trusted model), then the test checks the code matches that prediction.
+
+| Oracle type | Example |
+| -------------- | ------------------------------------------- |
+| Accept/reject | Empty room name must raise ValueError |
+| Round-trip | encode(decode(x)) == x when decode succeeds |
+| Jail | Successful path stays under storage root |
+| Closed reasons | Error message is one of a fixed set |
+| Membership | After PART by non-member, no PARTED fanout |
+
+## Hard refuse (soft fuzz)
+
+Do not ship tests that only do:
+
+- try/except pass around the unit under test
+- assert that a call did not raise, with no postcondition
+- assert response has key ok without checking True or False
+- mocks that always succeed under a security check
+
+## Workflow
+
+1. State the invariant in one sentence.
+2. Build inputs (Hypothesis strategy or explicit adversarial cases).
+3. Compute expected accept or reject without calling the buggy path if possible.
+4. Assert exact outcome (status, exception type, membership set, payload field).
+5. Cap examples and set deadline=None for CBOR/crypto-heavy cases.
+
+## MeshChatX examples
+
+- Protocol: `tests/backend/test_rrc_protocol_fuzz.py`
+- ACL/membership: `tests/backend/test_rrc_oracle_bugs.py`
+- Room keys: `tests/backend/test_rrc_room_keys.py`
+- EECT shared asserts: `tests/backend/eect/asserts.py`
+
+## Commands
+
+```bash
+uv run pytest tests/backend/test_rrc_oracle_bugs.py tests/backend/test_rrc_protocol_fuzz.py -q --tb=short
+task test:eect
+```
+
+Also read: `docs/agents/conventions/tests.md`, `docs/agents/skills/exploratory-testing/SKILL.md`.
diff --git a/meshchatx.rsm b/meshchatx.rsm
index 73e12456..1a959eab 100644
Binary files a/meshchatx.rsm and b/meshchatx.rsm differ
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────